﻿namespace SimpleWebServices.Configuration
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using SimpleWebServices.Data;
    using Xunit;

    public class ServiceLocatorFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(typeof(ServiceLocator).IsStatic());
        }

        [Fact]
        public void prop_ConfigFileName()
        {
            string expected = "windsor.config";
            string actual = ServiceLocator.ConfigFileName;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void prop_Initialised_getDefault()
        {
            ServiceLocator.Reset();

            Assert.False(ServiceLocator.Initialized);
        }

        [Fact]
        public void op_GetConfigFilePath_stringNull()
        {
            Assert.Throws<ArgumentNullException>(() => ServiceLocator.GetConfigFilePath(null));
        }

        [Fact]
        public void op_GetConfigFilePath_stringEmpty()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => ServiceLocator.GetConfigFilePath(string.Empty));
        }

        [Fact]
        public void op_GetConfigFilePath_string()
        {
            string fileName = "windsor.config";
            string path = ServiceLocator.GetConfigFilePath(fileName);

            Assert.True(File.Exists(path));
        }

        [Fact]
        public void op_GetConfigFilePath_stringMissing()
        {
            string fileName = "SomeMadeUpFileName.txt";
            string path = ServiceLocator.GetConfigFilePath(fileName);

            Assert.Contains("bin", path);
        }

        [Fact]
        public void op_Reset()
        {
            ServiceLocator.Reset();

            Assert.False(ServiceLocator.Initialized);
        }

        [Fact]
        public void op_Clear()
        {
            ServiceLocator.Reset();
            ServiceLocator.Clear();

            Assert.True(ServiceLocator.Initialized);
        }

        [Fact]
        public void op_Resolve_TInterface()
        {
            ServiceLocator.Clear();

            try
            {
                ServiceLocator.Register<IDummy, Dummy>("dummy");

                Assert.IsType<Dummy>(ServiceLocator.Resolve<IDummy>());
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_ComponentNotFound()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<KeyNotFoundException>(() => ServiceLocator.Resolve<IDummy>());
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_TInterfaceConcrete()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentInvalidGenericException>(() => ServiceLocator.Resolve<Dummy>());
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_stringNull()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentNullException>(() => ServiceLocator.Resolve<IDummy>(null as string));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_stringEmpty()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentOutOfRangeException>(() => ServiceLocator.Resolve<IDummy>(string.Empty));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_stringUnknown()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<KeyNotFoundException>(() => ServiceLocator.Resolve<IDummy>(Token.New()));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Resolve_TInterface_string()
        {
            ServiceLocator.Clear();

            try
            {
                ServiceLocator.Register<IDummy, Dummy>("1");
                ServiceLocator.Register<IDummy, Dummy2>("2");

                Assert.IsType<Dummy2>(ServiceLocator.Resolve<IDummy>("2"));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcrete()
        {
            ServiceLocator.Clear();

            try
            {
                ServiceLocator.Register<IDummy, Dummy>();

                Assert.IsType<Dummy>(ServiceLocator.Resolve<IDummy>());
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcrete_string()
        {
            ServiceLocator.Clear();

            try
            {
                ServiceLocator.Register<IDummy, Dummy>("dummy");

                Assert.IsType<Dummy>(ServiceLocator.Resolve<IDummy>("dummy"));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcrete_stringNull()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentNullException>(() => ServiceLocator.Register<IDummy, Dummy>(null));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcrete_stringEmpty()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentOutOfRangeException>(() => ServiceLocator.Register<IDummy, Dummy>(string.Empty));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterfaceConcrete_TConcrete_string()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentInvalidGenericException>(() => ServiceLocator.Register<Dummy, Dummy>("dummy"));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcreteInterface_string()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentInvalidGenericException>(() => ServiceLocator.Register<IDummy, IDummy>("dummy"));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_TConcreteAbstract_string()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentInvalidGenericException>(() => ServiceLocator.Register<IDummy, AbstractDummy>("dummy"));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_objectNull()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentNullException>(() => ServiceLocator.Register<IDummy>(null));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterfaceConcrete_object()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentInvalidGenericException>(() => ServiceLocator.Register<Dummy>(new Dummy()));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_TInterface_object()
        {
            ServiceLocator.Clear();

            try
            {
                Dummy expected = new Dummy();

                ServiceLocator.Register<IDummy>(expected);

                IDummy actual = ServiceLocator.Resolve<IDummy>();

                Assert.Same(expected, actual);
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_string_object()
        {
            ServiceLocator.Clear();

            try
            {
                Dummy expected = new Dummy();

                ServiceLocator.Register("key", expected);

                IDummy actual = ServiceLocator.Resolve<IDummy>("key");

                Assert.Same(expected, actual);
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_string_objectNull()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentNullException>(() => ServiceLocator.Register("key", null as object));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_stringEmpty_object()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentOutOfRangeException>(() => ServiceLocator.Register(string.Empty, new Dummy()));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }

        [Fact]
        public void op_Register_stringNull_object()
        {
            ServiceLocator.Clear();

            try
            {
                Assert.Throws<ArgumentNullException>(() => ServiceLocator.Register(null as string, new Dummy()));
            }
            finally
            {
                ServiceLocator.Reset();
            }
        }
    }
}
